#include "napi/native_api.h"
#include "mavlink_wrapper.h"

static napi_value Parse(napi_env env, napi_callback_info info)
{
    napi_status status;

    // --- Step 1: 获取参数 ---
    size_t argc = 1;
    napi_value argv[1];
    status = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
    if (status != napi_ok || argc < 1) {
        napi_throw_error(env, nullptr, "parse() requires 1 argument");
        return nullptr;
    }

    uint8_t* buffer = nullptr;
    size_t len = 0;

    // --- Step 2: 判断是否为 TypedArray ---
    napi_typedarray_type type;
    void* data;
    size_t length;
    napi_value arraybuffer;
    size_t byteOffset;

    status = napi_get_typedarray_info(
        env,
        argv[0],
        &type,
        &length,
        &data,
        &arraybuffer,
        &byteOffset
    );

    if (status != napi_ok) {
        napi_throw_error(env, nullptr, "Failed to read TypedArray");
        return nullptr;
    }

    buffer = (uint8_t*)data;
    len = length;

    // --- Step 4: Debug 输出数据 ---
    printf("Parse() received %zu bytes: ", len);
    for (size_t i = 0; i < len; i++) printf("%02X ", buffer[i]);
    printf("\n");

    // --- Step 5: 调用 MAVLink 解析 ---
    mavlink_message_t msg;
    int ok = parse_mavlink_message(buffer, len, &msg);

    // --- Step 6: 返回 msgid 或 -1 ---
    napi_value result;
    napi_create_int32(env, ok ? msg.msgid : -1, &result);
    return result;
}

static napi_value PackHeartbeat(napi_env env, napi_callback_info info)
{
    mavlink_message_t msg;
    pack_heartbeat(1, 1, &msg);

    uint8_t buffer[MAVLINK_MAX_PACKET_LEN];
    int len = mavlink_msg_to_send_buffer(buffer, &msg);

    // Create ArrayBuffer
    napi_value arrayBuffer;
    void* data = nullptr;
    napi_create_arraybuffer(env, len, &data, &arrayBuffer);
    memcpy(data, buffer, len);

    // Create Uint8Array View
    napi_value typedArray;
    napi_create_typedarray(env, napi_uint8_array, len, arrayBuffer, 0, &typedArray);

    return typedArray;
}

// helper to print hex
static void print_hex(const uint8_t* buf, size_t len) {
    for (size_t i = 0; i < len; ++i) {
        printf("%02X ", buf[i]);
    }
    printf("\n");
}

static napi_value TestPackAndParseNative(napi_env env, napi_callback_info info) {
    // 1) pack
    mavlink_message_t msg;
    mavlink_msg_heartbeat_pack(
        1, 1, &msg,
        MAV_TYPE_QUADROTOR,
        MAV_AUTOPILOT_GENERIC,
        MAV_MODE_MANUAL_ARMED,
        0,
        MAV_STATE_STANDBY
    );
    uint8_t buffer[MAVLINK_MAX_PACKET_LEN];
    int len = mavlink_msg_to_send_buffer(buffer, &msg);

    printf("Packed buffer (%d bytes): ", len);
    print_hex(buffer, len);

    // 2) reset channel state BEFORE parsing (very important)
    mavlink_status_t* ch_status = mavlink_get_channel_status(MAVLINK_COMM_0);
    mavlink_message_t* ch_rxmsg = mavlink_get_channel_buffer(MAVLINK_COMM_0);
    if (ch_status && ch_rxmsg) {
        ch_status->parse_state = MAVLINK_PARSE_STATE_IDLE;
        ch_status->msg_received = 0;
        ch_rxmsg->len = 0;
        // optionally reset checksum state
        // mavlink_start_checksum(ch_rxmsg); // not necessary here
    }

    // 3) parse byte-by-byte and log return values
    mavlink_message_t out;
    mavlink_status_t status;
    int parsed = 0;
    for (int i = 0; i < len; ++i) {
        uint8_t res = mavlink_parse_char(MAVLINK_COMM_0, buffer[i], &out, &status);
        printf("byte[%d]=%02X -> mavlink_parse_char returned %d, parse_state=%d, msg_received=%d\n",
               i, buffer[i], res, status.parse_state, status.msg_received);
        if (res) { parsed = 1; break; }
    }

    printf("Parsed=%d, msgid=%d\n", parsed, parsed ? out.msgid : -1);

    // return msgid as JS number for convenience
    napi_value jsResult;
    napi_create_int32(env, parsed ? out.msgid : -1, &jsResult);
    return jsResult;
}

EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports)
{
    napi_property_descriptor desc[] = {
        { "parse", nullptr, Parse, nullptr, nullptr, nullptr, napi_default, nullptr },
        { "packHeartbeat", nullptr, PackHeartbeat, nullptr, nullptr, nullptr, napi_default, nullptr },
        { "testPackAndParseNative", nullptr, TestPackAndParseNative, nullptr, nullptr, nullptr, napi_default, nullptr }
    };
    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    return exports;
}
EXTERN_C_END

static napi_module demoModule = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Init,
    .nm_modname = "mavlink",
    .nm_priv = ((void*)0),
    .reserved = { 0 },
};

extern "C" __attribute__((constructor)) void RegisterMavlinkModule(void)
{
    napi_module_register(&demoModule);
}
